package com.slipper.system.sequence.service;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.slipper.common.transaction.ReadTransactional;
import com.slipper.common.transaction.WriteTransactional;
import com.slipper.common.util.DateUtil;
import com.slipper.common.util.Tool;
import com.slipper.system.api.sequence.bo.SequenceBO;
import com.slipper.system.sequence.dao.SequenceDao;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Calendar;
import java.util.Date;
import java.util.List;

@Service
@ReadTransactional
public class SequenceService {
    @Resource
    private SequenceDao sequenceDao;

    /**
     * 获取当前编号
     */
    public String getNextSequenceById(String id) {
        SequenceBO sequenceBO = this.sequenceDao.lockById(id);
        String sequence = generateSequence(sequenceBO);
        this.sequenceDao.update(sequenceBO);
        return sequence;
    }

    /**
     * 获取当前编号
     * @param flagId 标识
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public String getNextSequence(String flagId) {
        SequenceBO sequenceBO = this.sequenceDao.lockByFlagId(flagId);
        String sequence = generateSequence(sequenceBO);
        this.sequenceDao.update(sequenceBO);
        return sequence;
    }

    private String generateSequence(SequenceBO sequence) {
        String prefix = sequence.getPrefix() == null ? "" : sequence.getPrefix();
        String suffix = sequence.getSuffix() == null ? "" : sequence.getSuffix();
        long curNumber = sequence.getCurrNumber() == null ? 1L : sequence.getCurrNumber();
        Integer totalBit = sequence.getTotalBit();
        prefix = this.changeDate(prefix);
        suffix = this.changeDate(suffix);
        if (!prefix.equals(sequence.getCurPrefix())) {
            sequence.setCurPrefix(prefix);
            curNumber = 1L;
            sequence.setCurrNumber(curNumber);
        }
        StringBuilder sCurNumber = new StringBuilder();
        int len = totalBit - (prefix + suffix + curNumber).length();
        if (len > 0) {
            for (int i = 0; i < len; i++) {
                sCurNumber.append("0");
            }
            sCurNumber.append(curNumber);
        } else {
            sCurNumber = new StringBuilder(Long.toString(curNumber));
        }
        sequence.setCurrNumber(sequence.getCurrNumber() + 1);
        return prefix + sCurNumber + suffix;
    }

    private String changeDate(String s) {
        if (s == null || s.isEmpty()) {
            return "";
        }

        Calendar calender = Calendar.getInstance();
        calender.setTime(new Date());
        if (s.contains("{yyyyMMddHHmm}")) {
            s = s.replaceAll("\\{yyyyMMddHHmm}", DateUtil.format(calender.getTime(), "yyyyMMddHHmm"));
        }
        if (s.contains("{yyyyMMddHH}")) {
            s = s.replaceAll("\\{yyyyMMddHH}", DateUtil.format(calender.getTime(), "yyyyMMddHH"));
        }
        if (s.contains("{yyyyMMdd}")) {
            s = s.replaceAll("\\{yyyyMMdd}", DateUtil.format(calender.getTime(), "yyyyMMdd"));
        }
        if (s.contains("{yyyyMM}")) {
            s = s.replaceAll("\\{yyyyMM}", DateUtil.format(calender.getTime(), "yyyyMM"));
        }
        if (s.contains("{year}")) {
            s = s.replaceAll("\\{year}", "" + calender.get(Calendar.YEAR));
        }
        if (s.contains("{month}")) {
            s = s.replaceAll("\\{month}", "" + (calender.get(Calendar.MONTH) + 1));
        }
        if (s.contains("{day}")) {
            s = s.replaceAll("\\{day}", "" + calender.get(Calendar.DATE));
        }
        if (s.contains("{hour}")) {
            s = s.replaceAll("\\{hour}", "" + calender.get(Calendar.HOUR));
        }
        if (s.contains("{minute}")) {
            s = s.replaceAll("\\{minute}", "" + calender.get(Calendar.MINUTE));
        }
        if (s.contains("{second}")) {
            s = s.replaceAll("\\{second}", "" + calender.get(Calendar.SECOND));
        }
        return s;
    }
    
    public SequenceBO queryBy(String id) {
        return sequenceDao.queryBy(id);
    }
    
    public List<SequenceBO> queryList(SequenceBO bo) {
        return sequenceDao.queryList(bo);
    }
    
    public PageInfo<SequenceBO> queryPage(SequenceBO bo) {
        PageHelper.startPage(bo.getPageNumber(), bo.getPageSize());
        return new PageInfo<>(sequenceDao.queryList(bo));
    }
    
    @WriteTransactional
    public int save(SequenceBO bo) {
        if (bo.getId() != null && !"".equals(bo.getId())) {
            return sequenceDao.update(bo);
        } else {
            bo.setId(Tool.getUUID());
            return sequenceDao.insert(bo);
        }
    }
    
    @WriteTransactional
    public int delete(SequenceBO bo) {
        return sequenceDao.delete(bo);
    }

    public static void main(String[] args) {
        System.out.println(("YHQ2022010815" + "" + 1).length());
    }


}
